package org.dreamfly.core.remote;

import org.dreamfly.core.remote.exception.ServiceException;
import org.dreamfly.core.remote.exception.ServiceRegistException;
import org.dreamfly.core.remote.register.ServiceProxyGenerator;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User: Gin
 * Date: 2010-11-27
 * Time: 2:31:39
 * To change this template use File | Settings | File Templates.
 */
public class ServiceRepositoryImpl implements ServiceRepository, BeanFactoryAware,
        InitializingBean, DisposableBean {

    /**
     * 服务接口和服务ID之间的分隔符号
     */
    private static final String KEY_SPAR = "_";

    /**
     * 服务代理生成器的后缀
     */
    private static final String PROXY_GENERATOR_END = "_generator";

    /**
     * 服务中心容器
     */
    private Map<String, Object> serviceContainer = null;

    /**
     * 服务Key列表，内部使用
     */
    private List<String> serviceNames = null;

    /**
     * Spring的Bean工厂
     */
    private BeanFactory beanFactory = null;

    /*
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
     */

    public void afterPropertiesSet() throws Exception {
        // initial container
        init();
    }

    /*
     * @see org.springframework.beans.factory.DisposableBean#destroy()
     */

    public void destroy() throws Exception {
        // release container
        destory();
    }

    /*
     * @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
     */

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    /*
     * @see com.alipay.xfiredemo.common.ServiceRepository#destory()
     */

    public void destory() {
        this.serviceContainer = null;
        this.serviceNames = null;
    }

    /*
     * @see com.alipay.common.service.repository.ServiceRepository#getService(java.lang.Class,
     *      java.lang.String)
     */

    public Object getService(Class serviceClass, String serviceId) throws ServiceException {

        if (serviceClass == null) {
            throw new ServiceException("serviceClass can't be null !");
        }

        if (serviceId == null || serviceId.length() == 0) {
            throw new ServiceException("serviceId can't be null or empty !");
        }

        String key = serviceId + KEY_SPAR + serviceClass.getName();

        if (!serviceNames.contains(key)) {
            throw new ServiceException("there is no such service in the repository !");
        }


        return serviceContainer.get(key);
    }

    /*
     * @see com.alipay.xfiredemo.common.ServiceRepository#init()
     */

    public void init() {
        this.serviceContainer = new HashMap<String, Object>();
        this.serviceNames = new ArrayList<String>();
    }

    /*
     * @see com.alipay.common.service.repository.ServiceRepository#registService(com.alipay.common.service.repository.ServiceModel)
     */

    public void registService(ServiceModel serviceModel) throws ServiceException {
        if (serviceModel == null) {
            throw new ServiceRegistException("serviceModel can't be null !");
        }

        if (serviceModel.getServiceClass() == null) {
            throw new ServiceRegistException("serviceClass can't be null !");
        }

        if (serviceModel.getServiceId() == null || serviceModel.getServiceId().length() == 0) {
            throw new ServiceRegistException("serviceId can't be null or empty !");
        }

        if (serviceModel.getServiceType() == null || serviceModel.getServiceType().length() == 0) {
            throw new ServiceRegistException("serviceType can't be null or empty !");
        }

        if (serviceModel.getServiceUrl() == null || serviceModel.getServiceUrl().length() == 0) {
            throw new ServiceRegistException("serviceUrl can't be null or empty !");
        }

        String key = serviceModel.getServiceId() + KEY_SPAR
                + serviceModel.getServiceClass().getName();

        if (serviceNames.contains(key)) {
            throw new ServiceRegistException("service is exist!");
        }



        try {
            Object proxy = null;

            ServiceProxyGenerator proxyGenerator = (ServiceProxyGenerator) beanFactory
                    .getBean(serviceModel.getServiceType() + PROXY_GENERATOR_END);

            proxy = proxyGenerator.getService(serviceModel.getServiceClass(), serviceModel
                    .getServiceUrl(), serviceModel.getProps());

            if (proxy != null) {
                serviceNames.add(key);
                serviceContainer.put(key, proxy);
            } else {
                throw new ServiceRegistException("fail to regist service !");
            }
        } catch (Exception e) {
            throw new ServiceRegistException("can't regist service !", e);
        }

        /*if (proxy != null) {
            serviceNames.add(key);
            serviceContainer.put(key, proxy);
        } else {
            throw new ServiceRegistException("fail to regist service !");
        }*/
    }

    /*
     * @see com.alipay.xfiredemo.common.ServiceRepository#removeService(java.lang.Class,
     *      java.lang.String)
     */

    public void removeService(Class serviceClass, String serviceId) throws ServiceException {

        if (serviceClass == null) {
            throw new ServiceException("serviceClass can't be null !");
        }

        if (serviceId == null || serviceId.length() == 0) {
            throw new ServiceException("serviceId can't be null or empty !");
        }

        String key = serviceId + KEY_SPAR + serviceClass.getName();

        if (serviceNames.contains(key)) {
            serviceNames.remove(key);
            serviceContainer.remove(key);
        } else {
            throw new ServiceException("there is no such service in the repository !");
        }
    }

}
